package com.matuw.android.adapter.dataset;


import androidx.annotation.NonNull;


import com.matuw.android.adapter.UniversalAdapter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;


/**
 * 默认实现的数据自动刷新扩展
 *
 * @param <DATA>
 */
public class QinArrayAdapterDataSet<DATA> implements AdapterDataSet<DATA> {

    @NonNull
    private final List<DATA> dataSet;

    /**
     * 数据源改变时自动刷新，默认自动刷新
     */
    private boolean autoNotify = true;

    private UniversalAdapter<?, ?> adapter;

    public QinArrayAdapterDataSet() {
        dataSet = new ArrayList<>();
    }

    public QinArrayAdapterDataSet(@NonNull List<DATA> dataSet) {
        this.dataSet = Objects.requireNonNull(dataSet);
    }

    public boolean isAutoNotify() {
        return autoNotify;
    }

    public void setAutoNotify(boolean autoNotify) {
        this.autoNotify = autoNotify;
    }

    @Override
    public boolean contains(DATA o) {
        return dataSet.contains(o);
    }

    @Override
    public boolean isEmpty() {
        return dataSet.isEmpty();
    }

    @Override
    public int size() {
        return dataSet.size();
    }

    @Override
    public void setAll(Collection<? extends DATA> c) {
        dataSet.clear();
        if (c != null) dataSet.addAll(c);
        if (autoNotify()) adapter.notifyDataSetChanged();
    }

    @Override
    public boolean add(DATA data) {
        return add(data, autoNotify());
    }

    @Override
    public boolean add(DATA data, boolean notify) {
        boolean result = dataSet.add(data);
        if (result && notify) {
            adapter.notifyItemInserted(dataSet.size());
        }
        return result;
    }

    @Override
    public boolean remove(DATA data) {
        return remove(data, autoNotify());
    }

    @Override
    public boolean remove(DATA o, boolean notify) {
        boolean result = dataSet.remove(o);
        if (result && notify) {
            adapter.notifyItemRemoved(dataSet.size());
        }
        return result;
    }

    @Override
    public boolean addAll(Collection<? extends DATA> c) {
        return addAll(c, autoNotify());
    }

    @Override
    public boolean addAll(Collection<? extends DATA> c, boolean notify) {
        if (c == null || c.isEmpty()) return true;

        boolean result = dataSet.addAll(c);

        if (result && notify) {
            int count = c.size();
            adapter.notifyItemRangeInserted(dataSet.size() - count, count);
        }

        return result;
    }

    @Override
    public boolean addAll(int index, Collection<? extends DATA> c) {
        return addAll(index, c, autoNotify());
    }

    @Override
    public boolean addAll(int index, Collection<? extends DATA> c, boolean notify) {
        if (c == null || c.isEmpty()) return true;

        boolean result = dataSet.addAll(index, c);
        if (result && notify) {
            adapter.notifyItemRangeInserted(index, c.size());
        }
        return result;
    }

    @Override
    public boolean removeAll(Collection<? extends DATA> c) {
        return removeAll(c, autoNotify());
    }

    @Override
    public boolean removeAll(Collection<? extends DATA> c, boolean notify) {
        boolean result = dataSet.removeAll(c);
        if (result && notify) {
            adapter.notifyItemRangeRemoved(dataSet.size(), c.size());
        }

        return result;
    }

    @Override
    public void clear() {
        clear(autoNotify());
    }

    @Override
    public void clear(boolean notify) {
        dataSet.clear();
        if (notify) adapter.notifyDataSetChanged();
    }

    @Override
    public DATA get(int index) {
        return dataSet.get(index);
    }

    @Override
    public DATA getOrNull(int index) {
        return index >= 0 && index < size() ? get(index) : null;
    }

    @Override
    public DATA set(int index, DATA element) {
        return set(index, element, autoNotify());
    }

    @Override
    public DATA set(int index, DATA element, boolean notify) {
        DATA data = dataSet.set(index, element);
        adapter.notifyItemChanged(index);
        return data;
    }

    @Override
    public void add(int index, DATA element) {
        add(index, element, autoNotify());
    }

    @Override
    public void add(int index, DATA element, boolean notify) {
        dataSet.add(index, element);
        if (notify) adapter.notifyItemInserted(index);
    }

    @Override
    public DATA remove(int index) {
        return remove(index, autoNotify());
    }

    @Override
    public DATA remove(int index, boolean notify) {
        if (index >= 0 && index < dataSet.size()) {
            DATA data = dataSet.remove(index);
            if (notify) adapter.notifyItemRemoved(index);
            return data;
        }
        return null;
    }

    @Override
    public int indexOf(DATA o) {
        return dataSet.indexOf(o);
    }

    @NonNull
    @Override
    public List<DATA> getDataSet() {
        return dataSet;
    }

    @Override
    public void setAdapter(@NonNull UniversalAdapter<?, ?> adapter) {
        this.adapter = Objects.requireNonNull(adapter);
    }

    @NonNull
    @Override
    public UniversalAdapter<?, ?> getAdapter() {
        return Objects.requireNonNull(adapter);
    }

    private boolean autoNotify() {
        return autoNotify && adapter != null;
    }

    @Override
    public int lastIndex() {
        return size() - 1;
    }
}
